﻿using FreeSql.DataAnnotations;
using GetMan.Core.Extensions;
using NLog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace GetMan.Core.Helpers
{
    /// <summary>
    /// 数据库操作
    /// </summary>
    public static class DBHelper
    {
        private static readonly Logger Logger;
        static DBHelper()
        {
            Logger = LogManager.GetCurrentClassLogger();
        }

        /// <summary>
        /// 注册数据库
        /// </summary>
        /// <param name="connectionString"></param>
        /// <param name="dbType"></param>
        /// <returns></returns>
        public static IFreeSql RegisterFreeSql(string connectionString, bool isMonitor, string dbType = "")
        {
            FreeSql.DataType sqlType = FreeSql.DataType.Sqlite;
            if (dbType.NotNull())
                sqlType = (FreeSql.DataType)Enum.Parse(typeof(FreeSql.DataType), dbType);
            IFreeSql fsql = new FreeSql.FreeSqlBuilder()
                .UseConnectionString(sqlType, connectionString)
                .UseMonitorCommand(cmd =>
                {
                    if (isMonitor && cmd.CommandText.NotNull())
                    {
                        Logger.Info(cmd.CommandText.Replace("\r", "").Replace("\n", "").Replace("\t", ""));
                    }
                })
                .UseAutoSyncStructure(true)
                .Build();
            return fsql;
        }

        /// <summary>
        /// 同步结构
        /// </summary>
        public static void SyncStructure(IFreeSql db, string[] assemblyNames)
        {
            //打印结构比对脚本
            //var dDL = db.CodeFirst.GetComparisonDDLStatements<PermissionEntity>();
            //Console.WriteLine($"{Environment.NewLine} " + dDL);

            //打印结构同步脚本
            //db.Aop.SyncStructureAfter += (s, e) =>
            //{
            //    if (e.Sql.NotNull())
            //    {
            //        Console.WriteLine(" sync structure sql:\n" + e.Sql);
            //    }
            //};

            // 同步结构
            Logger.Info("开始同步数据库结构...");
            //获得指定程序集表实体
            var entityTypes = GetEntityTypes(assemblyNames);
            db.CodeFirst.SyncStructure(entityTypes);
            Logger.Info("完成同步数据库结构");

        }


        /// <summary>
        /// 获得指定程序集表实体
        /// </summary>
        /// <param name="assemblyNames"></param>
        /// <returns></returns>
        public static Type[] GetEntityTypes(string[] assemblyNames)
        {
            if (!(assemblyNames?.Length > 0))
            {
                return null;
            }
            var currAssemblies = AppDomain.CurrentDomain.GetAssemblies();
            Assembly[] assemblies = currAssemblies
                .Where(a => assemblyNames.Contains(a.GetName().Name))
                .Select(o => Assembly.Load(new AssemblyName(o.GetName().Name))).ToArray();

            var entityTypes = new List<Type>();

            foreach (var assembly in assemblies)
            {
                foreach (Type type in assembly.GetExportedTypes())
                {
                    foreach (Attribute attribute in type.GetCustomAttributes())
                    {
                        if (attribute is TableAttribute tableAttribute)
                        {
                            if (tableAttribute.DisableSyncStructure == false)
                            {
                                entityTypes.Add(type);
                            }
                        }
                    }
                }
            }

            return entityTypes.ToArray();
        }
    }
}